#pragma once
#include <sys/types.h>
#include <sys/socket.h>
#include <iostream>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include "Log.hpp"
#include "InetArr.hpp"

#define BACKLOG 8
#define DIE(num) (exit(num))

enum EXITCODE
{
    SOCKET_ERROR,
    BIND_ERROR,
    LISTEN_ERROR,
    READ_ERROR
};

const int gdefaultPort = 8080;
using namespace LogModule;

class TcpServer
{
public:
    TcpServer(uint16_t port = gdefaultPort) : _inetAddr(port),
                                              _isrunning(false),
                                              _listensockfd(-1),
                                              _espFd(-1),
                                              _qtFd(-1)
    {
    }

    void InitServer()
    {
        // 创建 bind 监听
        //  1. 创建socket
        _listensockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (_listensockfd < 0)
        {
            perror("socket error");
            DIE(SOCKET_ERROR);
        }

        // 2.加载进入内核
        int n = bind(_listensockfd, _inetAddr.NetAddr(), _inetAddr.NetAddrLen());
        if (n == -1)
        {
            perror("bind error");
            DIE(BIND_ERROR);
        }
        std::cout << "bind success port:" << _inetAddr.Port() << std::endl;

        // 3.监听
        n = ::listen(_listensockfd, BACKLOG);
        if (n < 0)
        {
            DIE(LISTEN_ERROR);
        }
        std::cout << "listen success, sockfd is : " << _inetAddr.Port() << std::endl;
    }

    void Handle(int recv, int send)
    {
        while (true)
        {
            char buffer[1024];
            int n = ::read(recv, buffer, sizeof(buffer) - 1);

            if (n == 0)
            {
                break; // 读取结尾
            }
            else if (n == -1)
            {
                DIE(READ_ERROR);
            }
            buffer[n] = 0;
            if (recv == _espFd)
            {
                LOG(LogLevel::INFOMATION) << "from esp to qt:" << buffer;
            }
            else
            {
                LOG(LogLevel::INFOMATION) << "from qt to esp:" << buffer;
            }

            ::write(send, buffer, n);
        }
    }

    void Start()
    {
        _isrunning = true;

        while (true)
        {
            struct sockaddr_in peer;
            socklen_t peer_len = sizeof(peer);
            int sockfd = ::accept(_listensockfd, CONV(&peer), &peer_len);
            if (sockfd == -1)
            {
                LOG(LogLevel::ERROR) << "连接错误";
            }

            char ipbuffer[64];
            const char *ip = ::inet_ntop(AF_INET, &peer.sin_addr, ipbuffer, sizeof(ipbuffer));

            LOG(LogLevel::INFOMATION) << "连接成功,IP:" << ipbuffer << "fd:" << sockfd;

            if (_espFd == -1 || _qtFd == -1)
            {
                // 连接状态
                char buffer[1024];
                int n = ::read(sockfd, buffer, sizeof(buffer) - 1);
                buffer[n] = 0;
                if (strcmp("esp", buffer) == 0)
                {
                    _espFd = sockfd;
                }
                else if (strcmp("qt", buffer) == 0)
                {
                    _qtFd = sockfd;
                }
            }

            if (_espFd != -1 && _qtFd != -1)
            {
                LOG(LogLevel::INFOMATION) << "建立连接成功";
                // 发送数据阶段
                // esp->qt
                pid_t id = fork();
                if (id == 0)
                {

                    Handle(_espFd, _qtFd);
                    exit(0);
                }

                // qt->esp
                id = fork();
                if (id == 0)
                {
                    Handle(_qtFd, _espFd);
                    exit(0);
                }
            }
            else
            {
                LOG(LogLevel::INFOMATION) << "建立连接中........";
            }
        }
    }

private:
    int _listensockfd;
    bool _isrunning;
    InetAddr _inetAddr;
    int _espFd;
    int _qtFd;
};